/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MyEngine;

/**
 *
 * @author Pawel
 */
import java.util.ArrayList;
import Figures.*;
import java.awt.Point;


import org.encog.engine.network.activation.*;
import org.encog.mathutil.randomize.*;
import org.encog.ml.data.*;
import org.encog.ml.data.basic.*;
import org.encog.neural.networks.*;
import org.encog.neural.networks.layers.*;
import org.encog.neural.networks.training.propagation.resilient.*;
import org.encog.neural.som.training.*;
import org.encog.persist.*;
import java.io.*;

public class Neural {

    BasicNetwork network = new BasicNetwork();
    boolean playing;

    public Neural(boolean play)
    {
        this.playing = play;
        network = (BasicNetwork)EncogDirectoryPersistence.loadObject(new File("siec.eg"));
    }




    public double getNote(char[][] board, boolean White){
        double [] note = new double[1];
        double note1 = 0;
        double [] input = new double[64];

        for (int z1=0;z1<8;z1++)
          {
          for (int z2=0;z2<8;z2++)
          {

              switch (board[z1][z2])
              {
                  case 'K':
                      input[z1*8+z2] = 1;
                      break;

                  case 'Q':
                      input[z1*8+z2] = 0.8;
                      break;

                  case 'N':
                      input[z1*8+z2] = 0.6;
                      break;

                  case 'R':
                      input[z1*8+z2] = 0.4;
                      break;

                  case 'B':
                      input[z1*8+z2] = 0.2;
                      break;

                  case 'P':
                      input[z1*8+z2] = 0.1;
                      break;

                  case 'k':
                      input[z1*8+z2] = -1;
                      break;

                  case 'q':
                      input[z1*8+z2] = -0.8;
                      break;

                  case 'n':
                      input[z1*8+z2] = -0.6;
                      break;

                  case 'r':
                      input[z1*8+z2] = -0.4;
                      break;

                  case 'b':
                      input[z1*8+z2] = -0.2;
                      break;

                  case 'p':
                      input[z1*8+z2] = -0.1;
                      break;

                  default:
                      input[z1*8+z2] = 0;
                      break;

              }

          }
      }

        if (!playing)
        {
            for (int i=0; i<64; i++) input[i] = -1*input[i];
        }
        /*for(MLDataPair pair: trainingSet ) {
                final MLData output = network.compute(pair.getInput());
                System.out.println(pair.getInput().getData(0) + "," + pair.getInput().getData(1)
                                + ", actual=" + output.getData(0) + ",ideal=" + pair.getIdeal().getData(0));
        }*/
        network.compute(input, note);

        //deterministic correction
        note1 = evaluate(board, White);

        //whose move?
        if (White)
        {
            note1 = (note1+note[0])/10;
        }
        else
        {
            note1 = (-note1+note[0])/10;
        }
        
        //System.out.println("neural: " + note[0] + " determ:" + note1);
        return note1;

    }

    //deterministic evaluation of situation on the board
    public double evaluate(char[][] board, boolean kto)
    {
        int MaxPawnFileBins[] = new int[ 8 ];
        int MaxPawnColorBins[] = new int[ 2 ];
        int MaxTotalPawns;
        int PawnRams;
        int MaxMostAdvanced[] = new int[ 8 ];
        int MaxPassedPawns[] = new int[ 8 ];
        int MinPawnFileBins[] = new int[ 8 ];
        int MinMostBackward[] = new int[ 8 ];

        int score = 0;
        int numpawnswhite = 0, numpawnsblack = 0;

        boolean whq = false, blq = false;
        boolean whr = false, blr = false;

        //first we analyze pawn structure
        // Look at pawn positions to be able to detect features such as doubled,
        // isolated or passed pawns

        // Reset the counters
        for(int i = 0; i < 8; i++ )
        {
          MaxPawnFileBins[ i ] = 0;
          MinPawnFileBins[ i ] = 0;
        }
        MaxPawnColorBins[ 0 ] = 0;
        MaxPawnColorBins[ 1 ] = 0;
        PawnRams = 0;
        MaxTotalPawns = 0;

        // Now, perform the analysis
        if ( kto )
        {
          for( int i = 0; i < 8; i++ )
          {
            MaxMostAdvanced[ i ] = 0;
            MinMostBackward[ i ] = 0;
            MaxPassedPawns[ i ] = 0;
          }

          for (int i=0; i<8; i++)
              for (int j=0; j<8; j++)
              {

                  if (board[j][i] == 'P')
                  {
                      // What is the pawn's position, in rank-file terms?
                      int rank = (i*8+j) >> 3;
                      int file = (i*8+j) % 8;

                      // This pawn is now the most advanced of all white pawns on its file
                      MaxPawnFileBins[ file ]++;
                      MaxTotalPawns++;
                      MaxMostAdvanced[ file ] = (i*8+j);

                      // Is this pawn on a white or a black square?
                      if ( ( rank % 2 ) == ( file % 2 ) )
                        MaxPawnColorBins[ 0 ]++;
                      else
                        MaxPawnColorBins[ 1 ]++;

                      // Look for a "pawn ram", i.e., a situation where a black pawn
                      // is located in the square immediately ahead of this one.
                      if ( i>0 && board[j][i-1] =='p' )
                        PawnRams++;
                  }
                  // Now, look for a BLACK pawn
                  else if (board[j][i] == 'p')
                  {
                      // If the black pawn exists, it is the most backward found so far
                      // on its file
                      int file = (i*8+j) % 8;
                      MinPawnFileBins[ file ]++;
                      MinMostBackward[ file ] = (i*8+j);

                  }

              }
        }
        else // Analyze from Black's perspective
        {
          for( int i = 0; i < 8; i++ )
          {
            MaxMostAdvanced[ i ] = 63;
            MaxPassedPawns[ i ] = 63;
            MinMostBackward[ i ] = 63;
          }
          for (int i=0; i<8; i++)
              for (int j=0; j<8; j++)
              {
                  if (board[j][i] == 'p')
                  {
                      // What is the pawn's position, in rank-file terms?
                      int rank = (i*8+j) >> 3;
                      int file = (i*8+j) % 8;

                      // This pawn is now the most advanced of all black pawns on its file
                      MaxPawnFileBins[ file ]++;
                      MaxTotalPawns++;
                      MaxMostAdvanced[ file ] = (i*8+j);

                      // Is this pawn on a white or a black square?
                      if ( ( rank % 2 ) == ( file % 2 ) )
                        MaxPawnColorBins[ 0 ]++;
                      else
                        MaxPawnColorBins[ 1 ]++;

                      // Look for a "pawn ram", i.e., a situation where a white pawn
                      // is located in the square immediately ahead of this one.
                      if ( i<7 && board[j][i+1] =='P' )
                        PawnRams++;
                  }
                  // Now, look for a WHITE pawn
                  else if (board[j][i] == 'P')
                  {
                      // If the white pawn exists, it is the most backward found so far
                      // on its file
                      int file = (i*8+j) % 8;
                      MinPawnFileBins[ file ]++;
                      MinMostBackward[ file ] = (i*8+j);

                  }

              }
        }

        //material evaluation
        // Compute the board's material balance, from the point of view of the "side"
        // player.  This is an exact clone of the eval function in CHESS 4.5
        int material_score_white = 0, material_score_black = 0, material_score=0;

        for (int i=0; i<8; i++)
        {
            for (int j=0; j<8; j++)
            {
                switch (board[j][i])
                {
                    case 'K':
                          material_score_white += 10;
                          break;

                      case 'Q':
                          material_score_white += 8;
                          whq = true;
                          break;

                      case 'N':
                          material_score_white += 2;
                          break;

                      case 'R':
                          material_score_white += 6;
                          whr = true;
                          break;

                      case 'B':
                          material_score_white += 4;
                          break;

                      case 'P':
                          numpawnswhite++;
                          break;

                      case 'k':
                          material_score_black += 10;
                          break;

                      case 'q':
                          material_score_black += 8;
                          blq = true;
                          break;

                      case 'n':
                          material_score_black += 2;
                          break;

                      case 'r':
                          material_score_black += 6;
                          blr = true;
                          break;

                      case 'b':
                          material_score_black += 4;
                          break;

                      case 'p':
                          numpawnsblack++;
                          break;
                }
            }
        }

        int matTotal = material_score_white + material_score_black;
        int matDiff = material_score_white - material_score_black;
        if (matDiff>0)
        {
            material_score = Math.min( 2400, matDiff ) +
                  ( matDiff * ( 12000 - matTotal ) * numpawnswhite )
                  / ( 6400 * ( numpawnsblack + 1 ) );
            if (!kto) material_score = -material_score;
        }
        else if (matDiff<0)
        {
            matDiff = -matDiff;
            material_score = Math.min( 2400, matDiff ) +
                  ( matDiff * ( 12000 - matTotal ) * numpawnsblack )
                  / ( 6400 * ( numpawnswhite + 1 ) );
            if (kto) material_score = -material_score;
        }



        //evaluating pawn structure
        // Given the pawn formations, penalize or bonify the position according to
        // the features it contains
        int pstruc_score = 0;

        // First, look for doubled pawns
        // In chess, two or more pawns on the same file usually hinder each other,
        // so we assign a minor penalty
        for( int bin = 0; bin < 8; bin++ )
          if ( MaxPawnFileBins[ bin ] > 1 )
            pstruc_score -= 8;

        // Now, look for an isolated pawn, i.e., one which has no neighbor pawns
        // capable of protecting it from attack at some point in the future
        if ( ( MaxPawnFileBins[ 0 ] > 0 ) && ( MaxPawnFileBins[ 1 ] == 0 ) )
          pstruc_score -= 15;
        if ( ( MaxPawnFileBins[ 7 ] > 0 ) && ( MaxPawnFileBins[ 6 ] == 0 ) )
          pstruc_score -= 15;
        for( int bin = 1; bin < 7; bin++ )
        {
          if ( ( MaxPawnFileBins[ bin ] > 0 ) && ( MaxPawnFileBins[ bin - 1 ] == 0 )
               && ( MaxPawnFileBins[ bin + 1 ] == 0 ) )
            pstruc_score -= 15;
        }

        // Assign a small penalty to positions in which Max still has all of his
        // pawns; this incites a single pawn trade (to open a file), but not by
        // much
        if ( MaxTotalPawns == 8 )
          pstruc_score -= 10;

        // Penalize pawn rams, because they restrict movement
        pstruc_score -= 8 * PawnRams;

        if ( kto )
        {
          if ( MaxMostAdvanced[ 0 ] < Math.min( MinMostBackward[ 0 ], MinMostBackward[ 1 ] ) )
            pstruc_score += ( 8 - ( MaxMostAdvanced[ 0 ] >> 3 ) ) *
                     ( 8 - ( MaxMostAdvanced[ 0 ] >> 3 ) );
          if ( MaxMostAdvanced[ 7 ] < Math.min( MinMostBackward[ 7 ], MinMostBackward[ 6 ] ) )
            pstruc_score += ( 8 - ( MaxMostAdvanced[ 7 ] >> 3 ) ) *
                     ( 8 - ( MaxMostAdvanced[ 7 ] >> 3 ) );
          for( int i = 1; i < 7; i++ )
          {
            if ( ( MaxMostAdvanced[ i ] < MinMostBackward[ i ] ) &&
                 ( MaxMostAdvanced[ i ] < MinMostBackward[ i - 1 ] ) &&
                 ( MaxMostAdvanced[ i ] < MinMostBackward[ i + 1 ] ) )
              pstruc_score += ( 8 - ( MaxMostAdvanced[ i ] >> 3 ) ) *
                       ( 8 - ( MaxMostAdvanced[ i ] >> 3 ) );
          }
        }
        else // from Black's perspective
        {
          if ( MaxMostAdvanced[ 0 ] > Math.max( MinMostBackward[ 0 ], MinMostBackward[ 1 ] ) )
            pstruc_score += ( MaxMostAdvanced[ 0 ] >> 3 ) *
                     ( MaxMostAdvanced[ 0 ] >> 3 );
          if ( MaxMostAdvanced[ 7 ] > Math.max( MinMostBackward[ 7 ], MinMostBackward[ 6 ] ) )
            pstruc_score += ( MaxMostAdvanced[ 7 ] >> 3 ) *
                     ( MaxMostAdvanced[ 7 ] >> 3 );
          for( int i = 1; i < 7; i++ )
          {
            if ( ( MaxMostAdvanced[ i ] > MinMostBackward[ i ] ) &&
                 ( MaxMostAdvanced[ i ] > MinMostBackward[ i - 1 ] ) &&
                 ( MaxMostAdvanced[ i ] > MinMostBackward[ i + 1 ] ) )
              pstruc_score += ( MaxMostAdvanced[ i ] >> 3 ) *
                       ( MaxMostAdvanced[ i ] >> 3 );
          }
        }


        //bad bishops evaluating
        // If Max has too many pawns on squares of the color of his surviving bishops,
        // the bishops may be limited in their movement

        int badbish_score = 0, ilu = 0;

        for( int i = 0; i < 8; i++ )
            for (int j=0; j<8; j++)
            {
              // Find a bishop
              if ( kto && board[j][i] == 'B')
              {
                // What is the bishop's square color?
                int rank = ( (i*8+j) >> 3 );
                int file = ( (i*8+j) % 8 );
                if ( ( rank % 2 ) == ( file % 2 ) )
                  badbish_score -= ( MaxPawnColorBins[ 0 ] << 3 );
                else
                  badbish_score -= ( MaxPawnColorBins[ 1 ] << 3 );

                ilu++;
              }
              else if (!kto && board[j][i] == 'b')
              {
                // What is the bishop's square color?
                int rank = ( (i*8+j) >> 3 );
                int file = ( (i*8+j) % 8 );
                if ( ( rank % 2 ) == ( file % 2 ) )
                  badbish_score -= ( MaxPawnColorBins[ 0 ] << 3 );
                else
                  badbish_score -= ( MaxPawnColorBins[ 1 ] << 3 );

                ilu++;
              }

              if (ilu == 2) break;

            }


        //development evaluation
        // Mostly useful in the opening, this term encourages the machine to move
        // its bishops and knights into play, to control the center with its queen's
        // and king's pawns, and to castle if the opponent has many major pieces on
        // the board

        int devel = 0;

        if (kto)
        {
            // Has the machine advanced its center pawns?
            if (board[3][6] == 'P') devel -= 15;
            if (board[4][6] == 'P') devel -= 15;

            // Penalize bishops and knights on the back rank

            for (int i=0; i<8; i++)
            {
                if (board[i][7] == 'B' || board[i][7] == 'N') devel -= 10;
            }

            // Penalize too-early queen movement

            if (whq)
            {
                int cnt=0;
                if (board[0][7] == 'R') cnt++;
                if (board[1][7] == 'N') cnt++;
                if (board[2][7] == 'B') cnt++;
                if (board[4][7] == 'K') cnt++;
                if (board[5][7] == 'B') cnt++;
                if (board[6][7] == 'N') cnt++;
                if (board[7][7] == 'R') cnt++;

                devel -= ( cnt << 3 );
            }

        }
        else // from black's perspective
        {
            // Has the machine advanced its center pawns?
            if (board[3][1] == 'p') devel -= 15;
            if (board[4][1] == 'p') devel -= 15;

            // Penalize bishops and knights on the back rank

            for (int i=0; i<8; i++)
            {
                if (board[i][0] == 'b' || board[i][0] == 'n') devel -= 10;
            }

            // Penalize too-early queen movement

            if (blq)
            {
                int cnt=0;
                if (board[0][0] == 'r') cnt++;
                if (board[1][0] == 'n') cnt++;
                if (board[2][0] == 'b') cnt++;
                if (board[4][0] == 'k') cnt++;
                if (board[5][0] == 'b') cnt++;
                if (board[6][0] == 'n') cnt++;
                if (board[7][0] == 'r') cnt++;

                devel -= ( cnt << 3 );
            }
        }


        //evaluation of rook bonus
        // Rooks are more effective on the seventh rank, on open files and behind
        // passed pawns
        int rookbonus = 0;

        if (kto && whr)
        {
            for (int i=0; i<8; i++)
                for (int j=0; j<8; j++)
                {
                    if (board[j][i] == 'R')
                    {
                        // Is this rook on the seventh rank?
                        int rank = (i*8+j) >> 3;
                        int file = (i*8+j) % 8;

                        if (rank == 7) rookbonus += 22;

                        // Is this rook on a semi- or completely open file?
                        if ( MaxPawnFileBins[ file ] == 0 )
                        {
                          if ( MinPawnFileBins[ file ] == 0 )
                            rookbonus += 10;
                          else
                            rookbonus += 4;
                        }

                        // Is this rook behind a passed pawn?
                        if (MaxPassedPawns[ file ] < (i*8+j)) rookbonus += 25;
                    }
                }
        }
        else if (!kto && blr) //black perspective
        {
            for (int i=0; i<8; i++)
                for (int j=0; j<8; j++)
                {
                    if (board[j][i] == 'r')
                    {
                        // Is this rook on the seventh rank?
                        int rank = (i*8+j) >> 3;
                        int file = (i*8+j) % 8;

                        if (rank == 0) rookbonus += 22;

                        // Is this rook on a semi- or completely open file?
                        if ( MaxPawnFileBins[ file ] == 0 )
                        {
                          if ( MinPawnFileBins[ file ] == 0 )
                            rookbonus += 10;
                          else
                            rookbonus += 4;
                        }

                        // Is this rook behind a passed pawn?
                        if (MaxPassedPawns[ file ] > (i*8+j)) rookbonus += 25;
                    }
                }
        }


        //king tropism evaluation
        // All other things being equal, having your Knights, Queens and Rooks close
        // to the opponent's king is a good thing
        // This method is a bit slow and dirty, but it gets the job done
        int tropism = 0;

        // Square coordinates
        int kingRank = 0, kingFile = 0;
        int pieceRank = 0, pieceFile = 0;

        if (kto)
        {
            // Look for enemy king first!
            for (int i=0; i<8; i++)
            {
                for (int j=0; j<8; j++)
                {
                    if ( board[j][i] == 'k' )
                    {
                        kingRank = (i*8+j) >> 3;
                        kingFile = (i*8+j) % 8;
                        break;
                    }
                }
            }

            // Now, look for pieces which need to be evaluated
          for (int i=0; i<8; i++)
            {
                for (int j=0; j<8; j++)
                {
                pieceRank = (i*8+j) >> 3;
                pieceFile = (i*8+j) % 8;

                switch( board[j][i] )
                {
                  case 'R':
                    tropism -= ( Math.min( Math.abs( kingRank - pieceRank ),
                                         Math.abs( kingFile - pieceFile ) ) << 1 );
                    break;
                  case 'N':
                    tropism += 5 - Math.abs( kingRank - pieceRank ) -
                                 Math.abs( kingFile - pieceFile );
                    break;
                  case 'Q':
                    tropism -= Math.min( Math.abs( kingRank - pieceRank ),
                                       Math.abs( kingFile - pieceFile ) );
                    break;
                  default:
                    break;
                }
                }
          }

        }
        else
        {
            // Look for enemy king first!
            for (int i=0; i<8; i++)
            {
                for (int j=0; j<8; j++)
                {
                    if ( board[j][i] == 'K' )
                    {
                        kingRank = (i*8+j) >> 3;
                        kingFile = (i*8+j) % 8;
                        break;
                    }
                }
            }

            // Now, look for pieces which need to be evaluated
          for (int i=0; i<8; i++)
            {
                for (int j=0; j<8; j++)
                {
                pieceRank = (i*8+j) >> 3;
                pieceFile = (i*8+j) % 8;

                switch( board[j][i] )
                {
                  case 'r':
                    tropism -= ( Math.min( Math.abs( kingRank - pieceRank ),
                                         Math.abs( kingFile - pieceFile ) ) << 1 );
                    break;
                  case 'n':
                    tropism += 5 - Math.abs( kingRank - pieceRank ) -
                                 Math.abs( kingFile - pieceFile );
                    break;
                  case 'q':
                    tropism -= Math.min( Math.abs( kingRank - pieceRank ),
                                       Math.abs( kingFile - pieceFile ) );
                    break;
                  default:
                    break;
                }
                }
          }
        }


        //summary
        //score = material_score;
        //score = pstruc_score;
        //score = badbish_score;
        //score = devel;
        //score = rookbonus;
        //score = tropism;
        score = material_score + pstruc_score + badbish_score +
                devel + rookbonus + tropism;
        return score;
    }


    public char[][] getActualBoard( char[][] b, ArrayList<int[]> moves) {
        char[][] board = new char[8][8];
        char[][] exBoard = {{'r','n','b','q','k','p','0'},
                            {'R','N','B','Q','K','P','0'}};

        for(int c = 0;c<=7; c++)
        for(int r = 0;r<=7; r++)board[c][r]=b[c][r];

        for(int m=0;m<moves.size();m++){
            if(moves.get(m)[1]<0){
                char figureType = exBoard[moves.get(m)[1]*(-1)-1][moves.get(m)[0]];
                 board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
                 continue;
            }
            else{
                    char figureType = board[moves.get(m)[0]][moves.get(m)[1]];
                 
                board[moves.get(m)[0]][moves.get(m)[1]]='0'; //we clear old location
                board[moves.get(m)[2]][moves.get(m)[3]]=figureType;
            }

        }
        return board;
    }

    private ArrayList<Figures> checkMyFigures(char[][] board,boolean isWhiteMove) {

        ArrayList<Figures> myFigures = new ArrayList();

        if(isWhiteMove){                          //if its white's move we are looking for capital letters
            for(int c = 0;c<=7; c++)
                for(int r = 0;r<=7; r++){
//                    char s = board[c][r];
//                    System.out.println(""+ s);
                    switch(board[c][r]){
                        case 'N': myFigures.add(new Knight(true, new Point(c,r)));
                                        break;
                        case 'B': myFigures.add(new Bishop(true,new Point(c,r)));
                                        break;
                        case 'P': myFigures.add(new Pawn(true,new Point(c,r)));
                                        break;
                        case 'K': myFigures.add(new King(true,new Point(c,r),false,false));
                                        break;
                        case 'R': myFigures.add(new Rouge(true,new Point(c,r)));
                                        break;
                        case 'Q': myFigures.add(new Queen(true,new Point(c,r)));
                                        break;
                    }
                }
        }
        else{
             for(int c = 0;c<=7; c++)
                for(int r = 0;r<=7; r++){
                    switch(board[c][r]){
                        case 'n': myFigures.add(new Knight(false, new Point(c,r)));
                                        break;
                        case 'b': myFigures.add(new Bishop(false,new Point(c,r)));
                                        break;
                        case 'p': myFigures.add(new Pawn(false,new Point(c,r)));
                                        break;
                        case 'k': myFigures.add(new King(false,new Point(c,r),false,false));
                                        break;
                        case 'r': myFigures.add(new Rouge(false,new Point(c,r)));
                                        break;
                        case 'q': myFigures.add(new Queen(false,new Point(c,r)));
                                        break;
                    }
                }
        }
        return myFigures;
    }


    public int isChecked(char [][] board, boolean spr) {

        int wh_x=-1, wh_y=-1, bl_x=-1, bl_y=-1;
        int isMated=0;

        for(int i=0;i<8;i++)
        {
            for (int j=0;j<8;j++)
            {
                if (board[i][j] == 'K')
                {
                    wh_x = i;
                    wh_y = j;
                }
                else if(board[i][j] == 'k')
                {
                    bl_x = i;
                    bl_y = j;
                }
            }
        }

        if (wh_x == -1 || wh_y == -1) return 100;
        else if (bl_x == -1 || bl_y == -1) return -100;

        boolean ifChecked=false;
        ArrayList<Figures> figures = new ArrayList();
        figures.add(new Knight(true, new Point(wh_x,wh_y)));
        figures.add(new Bishop(true, new Point(wh_x,wh_y)));
        figures.add(new Pawn(true, new Point(wh_x,wh_y)));
        figures.add(new King(true, new Point(wh_x,wh_y), false, false));
        figures.add(new Rouge(true, new Point(wh_x,wh_y)));
        figures.add(new Queen(true, new Point(wh_x,wh_y)));

        for(int f =0; f<figures.size();f++){
           ArrayList<Point> moves = figures.get(f).checkPossibleMoves(board);

           //if (moves.size()!=0) for (int z=0;z<moves.size();z++) System.out.println(""+moves.get(z).x + " " + moves.get(z).y);

           for(int m=0;m<moves.size();m++){
              int[] tmp = new int[4];
              tmp[0] = figures.get(f).getPosX();
              tmp[1] = figures.get(f).getPosY();
              tmp[2] = moves.get(m).x;
              tmp[3] = moves.get(m).y;

              switch (f)
              {
                  case (0):
                      if (board[tmp[2]][tmp[3]] == 'n') ifChecked = true;
                      break;

                  case (1):
                      if (board[tmp[2]][tmp[3]] == 'b') ifChecked = true;
                      break;

                  case (2):
                      if (board[tmp[2]][tmp[3]] == 'p') ifChecked = true;
                      break;

                  case (3):
                      if (board[tmp[2]][tmp[3]] == 'k') ifChecked = true;
                      break;

                  case (4):
                      if (board[tmp[2]][tmp[3]] == 'r') ifChecked = true;
                      break;

                  case (5):
                      if (board[tmp[2]][tmp[3]] == 'q') ifChecked = true;
                      break;
              }

              //System.out.println(f + " " + tmp[2] + " " + tmp[3] + " " + ifChecked);

            }
        }

        //white is checked?
        if (ifChecked)
        {
            if (spr) isMated = this.isMated(board, wh_x, wh_y, bl_x, bl_y);
            if (isMated == -1000) return -1000;
            return -100;
        }


        //for black:
        ArrayList<Figures> figures2 = new ArrayList();
        figures2.add(new Knight(!true, new Point(bl_x,bl_y)));
        figures2.add(new Bishop(!true, new Point(bl_x,bl_y)));
        figures2.add(new Pawn(!true, new Point(bl_x,bl_y)));
        figures2.add(new King(!true, new Point(bl_x,bl_y), false, false));
        figures2.add(new Rouge(!true, new Point(bl_x,bl_y)));
        figures2.add(new Queen(!true, new Point(bl_x,bl_y)));

        for(int f=0; f<figures2.size();f++){
           ArrayList<Point> moves2 = figures2.get(f).checkPossibleMoves(board);

           //if (moves.size()!=0) for (int z=0;z<moves.size();z++) System.out.println(""+moves.get(z).x + " " + moves.get(z).y);

           for(int m=0;m<moves2.size();m++){
              int[] tmp = new int[4];
              tmp[0] = figures2.get(f).getPosX();
              tmp[1] = figures2.get(f).getPosY();
              tmp[2] = moves2.get(m).x;
              tmp[3] = moves2.get(m).y;

              switch (f)
              {
                  case (0):
                      if (board[tmp[2]][tmp[3]] == 'N') ifChecked = true;
                      break;

                  case (1):
                      if (board[tmp[2]][tmp[3]] == 'B') ifChecked = true;
                      break;

                  case (2):
                      if (board[tmp[2]][tmp[3]] == 'P') ifChecked = true;
                      break;

                  case (3):
                      if (board[tmp[2]][tmp[3]] == 'K') ifChecked = true;
                      break;

                  case (4):
                      if (board[tmp[2]][tmp[3]] == 'R') ifChecked = true;
                      break;

                  case (5):
                      if (board[tmp[2]][tmp[3]] == 'Q') ifChecked = true;
                      break;
              }

              //System.out.println(f + " " + tmp[2] + " " + tmp[3] + " " + ifChecked);

            }
        }

        //black is checked?
        if (ifChecked)
        {
            if (isMated == 0 && spr) isMated = this.isMated(board, wh_x, wh_y, bl_x, bl_y);
            if (isMated == 1000) return 1000;
            return 100;
        }

        return 0;
    }

//    public int isMated(char [][] board,int wh_x,int wh_y,int bl_x,int bl_y) {
//
//        int mat = 1;
//
//     Point[] finalMove = new Point[2];
//     int childNr =0 ; //nr of child - needed in removing children
//     int isWhite=1;
//    char[][] newboard = new char[8][8];
//    for(int c = 0;c<=7; c++)
//     for(int r = 0;r<=7; r++){
//        newboard[c][r] = board[c][r];
//      }
//
//    ArrayList<Figures> figures = checkMyFigures(board,true);
//    //for(int f =0; f<figures.size();f++) System.out.println(figures.get(f).getClass());
//    //System.out.println("     ");
//     // tu mozna zmianic jak gleboko ma szukac w zaleznosci od tego ile jest figur na planszy
//    Node root = new Node();
//    for(int f =0; f<figures.size();f++){
//       ArrayList<Point> moves = figures.get(f).checkPossibleMoves(board);
//
//       //if (moves.size()!=0) for (int z=0;z<moves.size();z++) System.out.println(""+moves.get(z).x + " " + moves.get(z).y);
//       for(int m=0;m<moves.size();m++){
//          int[] tmp = new int[4];
//          tmp[0] = figures.get(f).getPosX();
//          tmp[1] = figures.get(f).getPosY();
//          tmp[2] = moves.get(m).x;
//          tmp[3] = moves.get(m).y;
//
//          Node node = new Node(root,tmp);
//          childNr++;
//
//          //System.out.println(figures.get(f).getClass());
//
//          newboard = getActualBoard(board,node.getMoves());//zamien liste ruchow na plansze i zapisz board<=plansza
//
//          if ((isChecked(board, false) == -100) && mat!=2) mat = -1000;
//          else mat = 2;
//
//       }
//    }
//
//        return mat;
//    }
    public int isMated(char [][] board,int wh_x,int wh_y,int bl_x,int bl_y) {

        int mat = 1;

     int childNr =0 ; //nr of child - needed in removing children
    char[][] newboard = new char[8][8];

    ArrayList<Figures> figures = checkMyFigures(board,true);
    //for(int f =0; f<figures.size();f++) System.out.println(figures.get(f).getClass());
    //System.out.println("     ");
     // tu mozna zmianic jak gleboko ma szukac w zaleznosci od tego ile jest figur na planszy
     Node root1 = new Node();

    for(int f =0; f<figures.size();f++){
       ArrayList<Point> moves = figures.get(f).checkPossibleMoves(board);

       //if (moves.size()!=0) for (int z=0;z<moves.size();z++) System.out.println(""+moves.get(z).x + " " + moves.get(z).y);
        for(int m=0;m<moves.size();m++){
          int[] tmp = new int[4];
          tmp[0] = figures.get(f).getPosX();
          tmp[1] = figures.get(f).getPosY();
          tmp[2] = moves.get(m).x;
          tmp[3] = moves.get(m).y;

          Node node = new Node(root1,tmp);
          childNr++;

          //System.out.println(figures.get(f).getClass());

          newboard = getActualBoard(board, node.getMoves());//zamien liste ruchow na plansze i zapisz board<=plansza

          if ((isChecked(newboard, false) == -100) && mat!=2) mat = -1000;
          else mat = 2;

       }
    }

    //for black:
    figures = checkMyFigures(board,false);
    //for(int f =0; f<figures.size();f++) System.out.println(figures.get(f).getClass());
     //System.out.println("     ");
     // tu mozna zmianic jak gleboko ma szukac w zaleznosci od tego ile jest figur na planszy
    root1 = new Node();

    for(int f =0; f<figures.size();f++){
        ArrayList<Point> moves = figures.get(f).checkPossibleMoves(board);

       //if (moves.size()!=0) for (int z=0;z<moves.size();z++) System.out.println(""+moves.get(z).x + " " + moves.get(z).y);
        for(int m=0;m<moves.size();m++){
          int[] tmp = new int[4];
          tmp[0] = figures.get(f).getPosX();
          tmp[1] = figures.get(f).getPosY();
          tmp[2] = moves.get(m).x;
          tmp[3] = moves.get(m).y;

          Node node = new Node(root1,tmp);
          childNr++;

          //System.out.println(figures.get(f).getClass());

          newboard = getActualBoard(board, node.getMoves());//zamien liste ruchow na plansze i zapisz board<=plansza

          if ((isChecked(newboard, false) == 100) && mat!=3 && mat != -1000) mat = 1000;
          else if (mat != -1000) mat = 3;

       }
    }
        return mat;
    }

        public static int TRAINING_SET_SIZE = 5000, CHECK_SET_SIZE=10000;
        //method training network from basic training set and experience
    public void doucz()
    {

        double [][] learn_input = new double[TRAINING_SET_SIZE+100][64];
        double [][] learn_output = new double[TRAINING_SET_SIZE+100][1];

        double [][] learn_input2 = new double[CHECK_SET_SIZE+100][64];
        double [][] learn_output2 = new double[CHECK_SET_SIZE+100][1];

        try{
                  FileInputStream fstream = new FileInputStream("!uczenie.txt");
                  DataInputStream in = new DataInputStream(fstream);
                  BufferedReader br = new BufferedReader(new InputStreamReader(in));
                  FileInputStream fstream2 = new FileInputStream("doucz.txt");
                  DataInputStream in2 = new DataInputStream(fstream2);
                  BufferedReader br2 = new BufferedReader(new InputStreamReader(in2));
                  String strLine;

                  int z1;
                  //Read File Line By Line
                  //for training set
                  for (z1=0;z1<TRAINING_SET_SIZE;z1++)
                  {
                      strLine = br.readLine();

                      for (int z2=0;z2<64;z2++)
                      {

                          switch (strLine.toCharArray()[z2])
                          {
                              case 'K':
                                  learn_input[z1][z2] = 100;
                                  break;

                              case 'Q':
                                  learn_input[z1][z2] = 80;
                                  break;

                              case 'N':
                                  learn_input[z1][z2] = 60;
                                  break;

                              case 'R':
                                  learn_input[z1][z2] = 40;
                                  break;

                              case 'B':
                                  learn_input[z1][z2] = 20;
                                  break;

                              case 'P':
                                  learn_input[z1][z2] = 10;
                                  break;

                              case 'k':
                                  learn_input[z1][z2] = -100;
                                  break;

                              case 'q':
                                  learn_input[z1][z2] = -80;
                                  break;

                              case 'n':
                                  learn_input[z1][z2] = -60;
                                  break;

                              case 'r':
                                  learn_input[z1][z2] = -40;
                                  break;

                              case 'b':
                                  learn_input[z1][z2] = -20;
                                  break;

                              case 'p':
                                  learn_input[z1][z2] = -10;
                                  break;

                              default:
                                  learn_input[z1][z2] = 0;
                                  break;

                          }

                          learn_output[z1][0] = Double.parseDouble(strLine.substring(64));

                      }
                  }

                    while ((strLine = br2.readLine()) != null && TRAINING_SET_SIZE+100<z1)
                    {
                        for (int z2=0;z2<64;z2++)
                      {

                          switch (strLine.toCharArray()[z2])
                          {
                              case 'K':
                                  learn_input[z1][z2] = 100;
                                  break;

                              case 'Q':
                                  learn_input[z1][z2] = 80;
                                  break;

                              case 'N':
                                  learn_input[z1][z2] = 60;
                                  break;

                              case 'R':
                                  learn_input[z1][z2] = 40;
                                  break;

                              case 'B':
                                  learn_input[z1][z2] = 20;
                                  break;

                              case 'P':
                                  learn_input[z1][z2] = 10;
                                  break;

                              case 'k':
                                  learn_input[z1][z2] = -100;
                                  break;

                              case 'q':
                                  learn_input[z1][z2] = -80;
                                  break;

                              case 'n':
                                  learn_input[z1][z2] = -60;
                                  break;

                              case 'r':
                                  learn_input[z1][z2] = -40;
                                  break;

                              case 'b':
                                  learn_input[z1][z2] = -20;
                                  break;

                              case 'p':
                                  learn_input[z1][z2] = -10;
                                  break;

                              default:
                                  learn_input[z1][z2] = 0;
                                  break;

                          }

                          learn_output[z1][0] = Double.parseDouble(strLine.substring(64));

                      }
                    }

                  //for comparison set
                  for (z1=0;z1<CHECK_SET_SIZE;z1++)
                  {
                      strLine = br.readLine();

                      for (int z2=0;z2<64;z2++)
                      {

                          switch (strLine.toCharArray()[z2])
                          {
                              case 'K':
                                  learn_input2[z1][z2] = 100;
                                  break;

                              case 'Q':
                                  learn_input2[z1][z2] = 80;
                                  break;

                              case 'N':
                                  learn_input2[z1][z2] = 60;
                                  break;

                              case 'R':
                                  learn_input2[z1][z2] = 40;
                                  break;

                              case 'B':
                                  learn_input2[z1][z2] = 20;
                                  break;

                              case 'P':
                                  learn_input2[z1][z2] = 10;
                                  break;

                              case 'k':
                                  learn_input2[z1][z2] = -100;
                                  break;

                              case 'q':
                                  learn_input2[z1][z2] = -80;
                                  break;

                              case 'n':
                                  learn_input2[z1][z2] = -60;
                                  break;

                              case 'r':
                                  learn_input2[z1][z2] = -40;
                                  break;

                              case 'b':
                                  learn_input2[z1][z2] = -20;
                                  break;

                              case 'p':
                                  learn_input2[z1][z2] = -10;
                                  break;

                              default:
                                  learn_input2[z1][z2] = 0;
                                  break;

                          }

                          learn_output2[z1][0] = Double.parseDouble(strLine.substring(64));

                      }
                  }

                  //Close the input stream
                  in.close();
                  in2.close();
                    }catch (Exception e){//Catch exception if any
                  System.err.println("Error: " + e.getMessage());
                  }

             // create a neural network
            BasicNetwork network = new BasicNetwork();
            BasicNetwork network2 = new BasicNetwork();

            //BEST:
            //4 4 3 = 4306; 4 3 = 4346; 4 = 4349; (100/1000)
            //30 30 20 = 24278; 40 30 30 = 24285; (1000/5000)
            //140 80 70 = 22867; 160 130 50 = 22501; 190 140 80 = 22121; (1000/5000)
            //250 180 120 = 39626 (5000/10000)

            //add some layers to neural network
            network.addLayer(new BasicLayer(new ActivationLOG(),true,64));
            network.addLayer(new BasicLayer(new ActivationLOG(),true, 250));
            network.addLayer(new BasicLayer(new ActivationLOG(),true, 180));
            network.addLayer(new BasicLayer(new ActivationLOG(),true, 120));
            network.addLayer(new BasicLayer(new ActivationLOG(),false,1));
            network.getStructure().finalizeStructure();
            network.reset();
            //initializing weights
            new ConsistentRandomizer(-1,1,456).randomize(network);
            System.out.println(network.dumpWeights());

            // create training data
            MLDataSet trainingSet = new BasicMLDataSet(learn_input, learn_output);
            //create set to check when network is overtrained
            MLDataSet trainingSet_check = new BasicMLDataSet(learn_input2, learn_output2);

            // train the neural network
            //final Backpropagation train = new Backpropagation(network, trainingSet, 0.7, 0.3);  //HUGE error
            final ResilientPropagation train = new ResilientPropagation(network, trainingSet);  // OK!
            //final LevenbergMarquardtTraining train = new LevenbergMarquardtTraining(network, trainingSet); //MEGATRONIX time of training

            int epoch = 1;
            double real_error=0, mean_error=0, min_error=1000000000;

            do {
                    real_error = 0;
                    train.iteration();
                    for(MLDataPair pair: trainingSet_check ) {
                            final MLData output = network.compute(pair.getInput());
                            //counitg error for another set, to chech on overtraining
                            real_error = real_error + Math.abs(output.getData(0) - pair.getIdeal().getData(0));
                            //System.out.println("actual=" + output.getData(0) + ",ideal=" + pair.getIdeal().getData(0));
                    }
                    System.out.println("Epoch #" + epoch + " Error:" + train.getError() +
                            "   Real error:" + real_error + " Min: " + min_error);
                    mean_error = mean_error + real_error;

                    //counting minimum of 'real error' and saving network that has it
                    if (real_error<min_error)
                    {
                        min_error = real_error;
                        //save
                        EncogDirectoryPersistence.saveObject(new File("siec.eg"), network);
                    }

                    epoch++;
            } while(train.getError() > 1 && epoch <= 1);

            mean_error = mean_error/epoch;

            // test the neural network
            //System.out.println("Neural Network Results:");
            //for(MLDataPair pair: trainingSet ) {
            //        final MLData output = network.compute(pair.getInput());
            //        System.out.println("actual=" + output.getData(0) + ",ideal=" + pair.getIdeal().getData(0));
            //}

            System.out.println("Mean Error: " + mean_error + "   Min Error: " + min_error);

            //loading saved network to check is this one really the best one
            network2 = (BasicNetwork)EncogDirectoryPersistence.loadObject(new File("siec.eg"));
            real_error = 0;
            for(MLDataPair pair: trainingSet_check )
            {
                    final MLData output = network2.compute(pair.getInput());
                    real_error = real_error + Math.abs(output.getData(0) - pair.getIdeal().getData(0));
            }
            System.out.println("Error: " + real_error + " Mean: " + real_error/((double) CHECK_SET_SIZE));

            //deleting file
            String fileName = "doucz.txt";
            File f = new File(fileName);

            // Make sure the file or directory exists and isn't write protected
            if (!f.exists())
              throw new IllegalArgumentException(
                  "Delete: no such file or directory: " + fileName);

            if (!f.canWrite())
              throw new IllegalArgumentException("Delete: write protected: "
                  + fileName);

            // If it is a directory, make sure it is empty
            if (f.isDirectory()) {
              String[] files = f.list();
              if (files.length > 0)
                throw new IllegalArgumentException(
                    "Delete: directory not empty: " + fileName);
            }

            // Attempt to delete it
            boolean success = f.delete();

            if (!success)
              throw new IllegalArgumentException("Delete: deletion failed");

    }

}
